package com.qizhou.base.dialog.lifecycledialog

import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.StyleRes
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import com.qizhou.base.dialog.lifecycledialog.cancelable.BaseCancelableHandler
import com.qizhou.base.dialog.lifecycledialog.cancelable.CanCancelHandler
import great.easychat.help.dialog.gravity.BaseDialogGravityHandler
import great.easychat.help.dialog.gravity.GravityEnum
import great.easychat.help.dialog.outlifecycle.OutLifecycleFragmentObserver
import java.lang.reflect.Field

abstract class BasePNdialogFragment<P, N> : DialogFragment() {


    var basePNdialogListener: BasePNdialogListener<P, N>? = null


    open fun setDefaultListener(defaultListener: BasePNdialogListener<P, N>): BasePNdialogFragment<P, N> {
        basePNdialogListener = defaultListener

        return this
    }

    val INVALID_LAYOUT_ID = -1;

    var dimAmount = -1f

    /**
     * 桥接对象--gravity处理者
     */
    var baseDialogGravityHandler: BaseDialogGravityHandler = BaseDialogGravityHandler(this)

    var baseCancelableHandler: BaseCancelableHandler = CanCancelHandler(this)

    val outLifecycleObservers = ArrayList<OutLifecycleFragmentObserver>()


    fun applyCancelable(cancelable: Boolean): BasePNdialogFragment<P, N> {
        baseCancelableHandler.cancelable = cancelable
        return this
    }

    fun applyDimAmount(dimAmount: Float): BasePNdialogFragment<P, N> {
        this.dimAmount = dimAmount
        return this
    }


    /**
     * 根据gravity的上下左右等具体位置，初始化gravity处理类的具体实例
     */
    fun applyGravityStyle(gravityEnum: GravityEnum): BasePNdialogFragment<P, N> {
        baseDialogGravityHandler.gravityEnum = gravityEnum
        return this
    }

    fun setAnimationStyle(@StyleRes resId: Int): BasePNdialogFragment<P, N> {
        baseDialogGravityHandler.animationStyleresId = resId
        return this
    }

    fun setXYPosition(xPosition: Int, yPosition: Int): BasePNdialogFragment<P, N> {
        baseDialogGravityHandler.xPosition = xPosition
        baseDialogGravityHandler.yPosition = yPosition
        return this
    }

//    fun show(fragmentManager: FragmentManager): BasePNdialogFragment<P, N> {
//        baseDialogGravityHandler = baseDialogGravityHandler.build()
//        baseCancelableHandler = baseCancelableHandler.build()
//        super.show(fragmentManager, javaClass.simpleName)
//        return this
//    }

    // 规避Can not perform this action after onSaveInstanceState异常，在后台时弹出dialog会报这个错误
    fun show(manager: FragmentManager): BasePNdialogFragment<P, N> {
        baseDialogGravityHandler = baseDialogGravityHandler.build()
        baseCancelableHandler = baseCancelableHandler.build()
        try {
            val mDismissed: Field = this.javaClass.superclass!!.getDeclaredField("mDismissed")
            val mShownByMe: Field = this.javaClass.superclass!!.getDeclaredField("mShownByMe")
            mDismissed.setAccessible(true)
            mShownByMe.setAccessible(true)
            mDismissed.setBoolean(this, false)
            mShownByMe.setBoolean(this, true)
        } catch (e: NoSuchFieldException) {
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
        }
        val ft: FragmentTransaction = manager.beginTransaction()
        ft.add(this, javaClass.simpleName)
        ft.commitAllowingStateLoss()
        return this
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.addObserver(baseDialogGravityHandler)
        addOutLifecycleObservers(baseDialogGravityHandler)
        lifecycle.addObserver(baseCancelableHandler)
    }

    /** The system calls this to get the DialogFragment's layout, regardless
     * of whether it's being displayed as a dialog or an embedded fragment.  */
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        var rootView: View?
        // Inflate the layout to use as dialog or embedded fragment
        if (getViewLayoutId() != INVALID_LAYOUT_ID) {
            rootView = inflater.inflate(getViewLayoutId(), container, false)
        } else {
            rootView = super.onCreateView(inflater, container, savedInstanceState)
        }
        createViewModelAndObserveLiveData()
        outLifecycleObservers.notifyOutLifecycleObservers {
            it.onCreateView(inflater, container, savedInstanceState)
        }
        return rootView
    }

    /**
     * 通过onCreateView方式配置的布局layoutId
     */
    abstract fun getViewLayoutId(): Int

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        init()
    }

    open fun createViewModelAndObserveLiveData() {}

    abstract fun init()


    override fun onStart() {
        super.onStart()
        if (dimAmount >= 0) {
            val window = dialog!!.window
            val windowParams = window!!.attributes
            windowParams.dimAmount = 0.0f
            window.attributes = windowParams
        }
    }

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)

        basePNdialogListener?.onDismiss(this, Any())
    }

    override fun onDestroyView() {
        super.onDestroyView()
        outLifecycleObservers.notifyOutLifecycleObservers { it.onDestroyView() }
        removeAllOutLifecycleObservers()
    }

    fun addOutLifecycleObservers(outLifecycleFragmentObserver: OutLifecycleFragmentObserver) {
        outLifecycleObservers.addIfAbsent(outLifecycleFragmentObserver)
    }

    fun removeAllOutLifecycleObservers() {
        outLifecycleObservers.clear()
    }

    fun removeOutLifecycleObservers(outLifecycleFragmentObserver: OutLifecycleFragmentObserver) {
        outLifecycleObservers.removeIfIn(outLifecycleFragmentObserver)
    }


    interface BasePNdialogListener<P, N> {

        fun onDialogPositiveClick(dialog: DialogFragment, any: P) {}
        fun onDialogNegativeClick(dialog: DialogFragment, any: N) {}

        fun onDismiss(dialog: DialogFragment, any: Any) {}
    }

}